const {VueLoaderPlugin} = require('vue-loader');
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const manifest = require("./manifest.json")

const pluginName = manifest.name;

class SourceToJsonStringPlugin {
    apply(compiler) {
        const pluginId = 'SourceToJsonStringPlugin';

        // 使用 Webpack 5 的 processAssets 钩子
        compiler.hooks.thisCompilation.tap(pluginId, (compilation) => {
            // 这个钩子在所有资源（assets）生成后运行，允许我们对它们进行最终处理
            compilation.hooks.processAssets.tap(
                {
                    name: pluginId,
                    // 在资源被优化（压缩）之后运行，确保我们处理的是最终代码
                    stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
                },
                (assets) => {
                    console.log(`[${pluginId}] 正在将JS源码 "${pluginName}.js" 转换为JSON字符串...`);

                    const sourceFileName = `${pluginName}.js`;
                    const targetFileName = manifest.main;

                    if (assets[sourceFileName]) {
                        const sourceCode = assets[sourceFileName].source().toString();

                        const jsonString = JSON.stringify(sourceCode);

                        compilation.emitAsset(
                            targetFileName,
                            new compiler.webpack.sources.RawSource(jsonString)
                        );

                        console.log(`[${pluginId}] 已成功创建 ${targetFileName}`);

                        compilation.deleteAsset(sourceFileName);
                    }
                }
            );
        });
    }
}

// experiments.outputModule 与 library.type: 'system' 是冲突的，不能同时使用
// 必须导出为 system 模块
// target必须为 web
module.exports = (env, argv) => {
    const isProduction = argv.mode === 'production';

    return {
        mode: isProduction ? 'production' : 'development',
        target: 'web',
        entry: './src/Plugin.vue',
        output: {
            path: path.resolve(__dirname, 'dist', pluginName),
            filename: `${pluginName}.js`,
            library: {
                type: 'system',
            },
            publicPath: `/plugins/${pluginName}/`,
            clean: true,
        },
        externalsType: 'system',
        externals: {
            vue: 'vue',
            WailsRunTime: "WailsRunTime",
            VConfigAPI: "VConfigAPI",
            VLoggerAPI: "VLoggerAPI",
            VPluginAPI: "VPluginAPI",
            VProcessAPI: "VProcessAPI",
            VUtilsAPI: "VUtilsAPI",
        },
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                },
                {
                    test: /\.ts$/,
                    loader: 'ts-loader',
                    options: {
                        appendTsSuffixTo: [/\.vue$/],
                        transpileOnly: true,
                    },
                    exclude: /bindings/,
                },
                {
                    test: /\.css$/,
                    use: [
                        'style-loader',
                        'css-loader',
                    ],
                    exclude: /theme.css/
                },
                {
                    test: /\.(png|jpe?g|gif|svg)$/i,
                    type: 'asset/resource',
                    generator: {
                        filename: 'images/[name][ext]'
                    }
                },
            ],
        },
        resolve: {
            extensions: ['.ts', '.js', '.vue', '.json'],
            alias: {
                '@': path.resolve(__dirname, 'src'),
            },
        },
        plugins: [
            new VueLoaderPlugin(),
            new CopyPlugin({
                patterns: [
                    {from: 'manifest.json', to: 'manifest.json'},
                ],
            }),
            new SourceToJsonStringPlugin(),
        ],
        optimization: {
            minimize: isProduction,
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        ecma: 2015,
                        compress: {},
                        mangle: true,
                        format: {
                            comments: false,
                        },
                    },
                    extractComments: false,
                }),
            ],
        },
    };
}
